home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / MISC / DTMFF110 / DTMF.C < prev    next >
C/C++ Source or Header  |  1997-08-05  |  7KB  |  274 lines

  1. /* DTMF.C */
  2. /* Author: Emil LAURENTIU */
  3. /* Last modified: Tuesday, 05 August 1997 */
  4.  
  5. #include <stdio.h>
  6. #include <conio.h>
  7. #include <dos.h>
  8. #include <string.h>
  9.  
  10. #include "freq.h"
  11.  
  12. extern char   matrix_dtmf[4][4];
  13. extern int    f_dtmf[];
  14. extern double f_ctcss[];
  15. extern int    sb_f_dtmf[];
  16. extern int    dtmf_delay;
  17. extern int    sb_addr;
  18.  
  19. static unsigned ticking = 0;
  20.  
  21. static FM_Instrument instrument = {
  22.   0x3f, 0x3f,            /* Level */
  23.   0x00, 0x00,            /* Multiple */
  24.   0x00, 0x00,            /* Attack */
  25.   0x00, 0x00,            /* Decay */
  26.   0x0f, 0x0f,            /* Sustain */
  27.   0x00, 0x00,            /* Release */
  28.   0x00, 0x00,            /* WaveSelect */
  29.   0x00, 0x00,            /* Amp_Vib_EnvG */
  30.   0x01, 0x00            /* Algorithm, Feedback */
  31. };
  32. int           notes[12] = {0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5,
  33. 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE};
  34.  
  35. /* dtmf.c 05/08/97 23.37.34 */
  36. unsigned char op_p( int voice, int op );
  37. void          Sb_FM_Reset( void );
  38. void          Sb_FM_Key_Off( int voice );
  39. void          Sb_FM_Key_On( int voice, int freq, int octave );
  40. void          Sb_FM_Voice_Volume( int voice, int op, int vol );
  41. void          Sb_FM_Voice_At_De( int voice, int op, int atack, int decay );
  42. void          Sb_FM_Voice_Su_Re( int voice, int op, int sustain, int release );
  43. void          Sb_FM_Voice_Character( int voice, int op, int amp_vib_envg, int multiple );
  44. void          Sb_FM_Voice_WaveSelect( int voice, int op, int wave );
  45. void          Sb_FM_Voice_FeedBack( int voice, int type, int strength );
  46. void          Sb_FM_Set_Voice( int voice, FM_Instrument * ins );
  47. void interrupt new_timer( void );
  48. unsigned long timer_hiticks( void );
  49. void          delay_loop( int time );
  50. void          generate_DTMF( char *nr );
  51. double        generate_CTCSS( int gen_ctcss );
  52.  
  53. static void
  54. WriteFM( int addr, unsigned char data )
  55. {
  56.   int           i;
  57.  
  58.   /* Left Channel */
  59.   outportb( sb_addr + 0, addr );
  60.   for ( i = 0; i < 6; i++ )
  61.     inportb( sb_addr + 0 );
  62.   outportb( sb_addr + 1, data );
  63.   for ( i = 0; i < 35; i++ )
  64.     inportb( sb_addr + 0 );
  65.   /* Rigth Channel */
  66.   outportb( sb_addr + 2, addr );
  67.   for ( i = 0; i < 6; i++ )
  68.     inportb( sb_addr + 2 );
  69.   outportb( sb_addr + 3, data );
  70.   for ( i = 0; i < 35; i++ )
  71.     inportb( sb_addr + 2 );
  72. }
  73.  
  74. unsigned char
  75. op_p( int voice, int op )
  76. {
  77.   unsigned char c;
  78.  
  79.   c = ( --voice ) % 9;
  80.   c = ( c / 3 ) << 3 | c % 3;
  81.   c += 3 * ( ( --op ) & 1 );
  82.   return ( c );
  83. }
  84.  
  85. void
  86. Sb_FM_Reset( void )
  87. {
  88.   int           i;
  89.  
  90.   WriteFM( 1, 0x20 );        /* FM waveform */
  91.   WriteFM( 4, 0 );        /* disable timers */
  92.   WriteFM( 8, 0 );        /* select FM music mode */
  93.   WriteFM( 0xbd, 0xc0 );    /* no drums */
  94.   for ( i = 1; i <= 9; i++ )
  95.   {
  96.     Sb_FM_Key_Off( i );
  97.     Sb_FM_Voice_WaveSelect( i, 1, 0 );
  98.     Sb_FM_Voice_WaveSelect( i, 2, 0 );
  99.   }
  100. }
  101.  
  102. void
  103. Sb_FM_Key_Off( int voice )
  104. {
  105.   WriteFM( 0xB0 + ( --voice ) % 9, 0 );    /* turn voice off */
  106. }
  107.  
  108. void
  109. Sb_FM_Key_On( int voice, int freq, int octave )
  110. {
  111.   --voice;
  112.   voice %= 9;
  113.   WriteFM( 0xb0 + voice, 0 );
  114.   WriteFM( 0xa0 + voice, freq & 0xff );
  115.   WriteFM( 0xb0 + voice, ( freq >> 8 ) | ( octave << 2 ) | 0x20 );
  116. }
  117.  
  118. void
  119. Sb_FM_Voice_Volume( int voice, int op, int vol )
  120. {
  121.   WriteFM( 0x40 + op_p( voice, op ), ~vol & 0x3f | 0x40 );
  122. }
  123.  
  124. void
  125. Sb_FM_Voice_At_De( int voice, int op, int atack, int decay )
  126. {
  127.   WriteFM( 0x60 + op_p( voice, op ), ( ~atack & 0xf ) << 4 | decay & 0xf );
  128. }
  129.  
  130. void
  131. Sb_FM_Voice_Su_Re( int voice, int op, int sustain, int release )
  132. {
  133.   WriteFM( 0x80 + op_p( voice, op ), ( sustain & 0xf ) << 4 | ~release & 0xf );
  134. }
  135.  
  136. void
  137. Sb_FM_Voice_Character( int voice, int op, int amp_vib_envg, int multiple )
  138. {
  139.   WriteFM( 0x20 + op_p( voice, op ), ( amp_vib_envg & 7 ) << 5 | ( multiple + 1 ) & 0xf );
  140. }
  141.  
  142. void
  143. Sb_FM_Voice_WaveSelect( int voice, int op, int wave )
  144. {
  145.   WriteFM( 0xe0 + op_p( voice, op ), wave & 3 );
  146. }
  147.  
  148. void
  149. Sb_FM_Voice_FeedBack( int voice, int type, int strength )
  150. {
  151.   WriteFM( 0xc0 + ( --voice ) % 9, ( strength & 7 ) << 1 | type & 1 );
  152. }
  153.  
  154. void
  155. Sb_FM_Set_Voice( int voice, FM_Instrument * ins )
  156. {
  157.   int           op;
  158.  
  159.   for ( op = 1; op <= 2; op++ )
  160.   {
  161.     Sb_FM_Voice_Volume( voice, op, ins->Level[op - 1] );
  162.     Sb_FM_Voice_At_De( voice, op, ins->Atack[op - 1], ins->Decay[op - 1] );
  163.     Sb_FM_Voice_Su_Re( voice, op, ins->Sustain[op - 1], ins->Release[op - 1] );
  164.     Sb_FM_Voice_Character( voice, op, ins->Amp_Vib_EnvG[op - 1], ins->Multiple[op - 1] );
  165.     Sb_FM_Voice_WaveSelect( voice, op, ins->WaveSelect[op - 1] );
  166.   }
  167.   Sb_FM_Voice_FeedBack( voice, ins->Algorithm, ins->Feedback );
  168. }
  169.  
  170. void          interrupt
  171. new_timer(  )
  172. {
  173.   ticking++;
  174.   outportb( 0x20, 0x20 );    /* Send EOI */
  175. }
  176.  
  177.  
  178. unsigned long
  179. timer_hiticks(  )
  180. {
  181.   outportb( 0x43, 0x00 );    /* Send latch command to 8253  counter 0 */
  182.   return ( ( unsigned long ) ticking << 16 ) |
  183.       ( unsigned ) -( inportb( 0x40 ) | ( inportb( 0x40 ) << 8 ) );
  184. }
  185.  
  186. void
  187. delay_loop( int time )        /* Delay is in milisecond increments */
  188. {
  189.   unsigned long val;
  190.  
  191.   val = timer_hiticks(  ) + 1193L * time;
  192.   while ( val > timer_hiticks(  ) );    /* Wait */
  193. }
  194.  
  195. void
  196. generate_DTMF( char *nr )
  197. {
  198.   int           i, j;
  199.   int           xoff = WINDOW_LEFT;
  200.   char          nc;
  201.   int           key;
  202.   void          interrupt( *old_int ) (  );
  203.  
  204.   disable(  );
  205.   old_int = getvect( 8 );    /* timer */
  206.   setvect( 8, new_timer );
  207.   enable(  );
  208.  
  209.   Sb_FM_Set_Voice( 1, &instrument );
  210.   Sb_FM_Set_Voice( 2, &instrument );
  211.   Sb_FM_Voice_Volume( 1, 1, 0x3f );
  212.   Sb_FM_Voice_Volume( 2, 1, 0x3f );
  213.   Sb_FM_Voice_Volume( 1, 2, 0x3f );
  214.   Sb_FM_Voice_Volume( 2, 2, 0x3f );
  215.   while ( *nr )
  216.   {
  217.     key = 0;
  218.     for ( i = 0; i < 4; i++ )
  219.       for ( j = 0; j < 4; j++ )
  220.     if ( matrix_dtmf[i][j] == *nr )
  221.     {
  222.       key++;
  223.       Sb_FM_Key_On( 1, sb_f_dtmf[i], 5 );
  224.       Sb_FM_Key_On( 2, sb_f_dtmf[j + 4], 6 );
  225.     }
  226.     nc = *( nr + 1 );
  227.     *( nr + 1 ) = 0;
  228.     draw_text_left( xoff, MGY, nr );
  229.     xoff += 8;
  230.     *( nr + 1 ) = nc;
  231.     if ( key )
  232.       delay_loop( dtmf_delay << 1 );
  233.     Sb_FM_Key_Off( 1 );
  234.     Sb_FM_Key_Off( 2 );
  235.     if ( !key )
  236.       delay_loop( dtmf_delay << 1 );
  237.     delay_loop( dtmf_delay );
  238.     nr++;
  239.   }
  240.   Sb_FM_Voice_Volume( 1, 1, 0 );
  241.   Sb_FM_Voice_Volume( 2, 1, 0 );
  242.   Sb_FM_Voice_Volume( 1, 2, 0 );
  243.   Sb_FM_Voice_Volume( 2, 2, 0 );
  244.  
  245.   disable(  );
  246.   setvect( 8, old_int );
  247.   enable(  );
  248. }
  249.  
  250. double
  251. generate_CTCSS( int gen_ctcss )
  252. {
  253.   double        err = 0;
  254.   const double  step = 1e5 / 2097152;
  255.   int           factor, multiply;
  256.  
  257.   if ( gen_ctcss == CTCSS_MAX )
  258.     Sb_FM_Key_Off( 3 );
  259.   else
  260.   {
  261.     Sb_FM_Set_Voice( 3, &instrument );
  262.     multiply = f_ctcss[gen_ctcss] / step / 1024;
  263.     multiply++;
  264.     WriteFM( 0x20 + op_p( 3, 1 ), multiply );    /* use freq * multiply */
  265.     WriteFM( 0x20 + op_p( 3, 2 ), multiply );    /* for better resolution */
  266.     factor = f_ctcss[gen_ctcss] / step / multiply + 0.5;
  267.     err = step * factor * multiply - f_ctcss[gen_ctcss];
  268.     Sb_FM_Key_On( 3, factor, 0 );    /* use ocatave 0 */
  269.     WriteFM( 0x40 + op_p( 3, 1 ), 0xC0 );    /* maximum volume (0x3F) */
  270.     WriteFM( 0x40 + op_p( 3, 2 ), 0xC0 );    /* 6 db/octave decrease */
  271.   }
  272.   return ( err );
  273. }
  274.